#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h> 
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>

#pragma pack(push, 1) // 取消结构体对齐
typedef struct 
{
	char name[100]; // 文件名
	uint64_t size;      // 文件大小
}file_info;
#pragma pack(pop)    // 恢复结构体对齐


uint64_t recv_data(int sock, uint64_t size, char* buff)
{
	unsigned int ret = 0;
	uint64_t recv_cnt = 0;

	while((ret = recv(sock, buff + recv_cnt, size - recv_cnt, 0)) > 0)
		recv_cnt += ret;

	return recv_cnt;
}


int main(int argc, char** argv)
{
	//第 1 步：创建监听套接字
	int sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock == -1)
	{
		perror("socket");
		exit(EXIT_FAILURE);
	}

	//第 3 步：连接服务器
	
	//指定服务器的地址
	struct sockaddr_in srv_addr;
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_addr.s_addr = inet_addr(argv[1]);
	srv_addr.sin_port = htons(atoi(argv[2]));

	if(connect(sock, (struct sockaddr*)&srv_addr,sizeof(srv_addr)) == -1)
	{
		perror("connect");
	}
	printf("服务器连接成功！\n");

	//第 4 步：收发数据
	
	uint64_t ret, rat, k;
	//char buff[1024];
	char* name;
	file_info fi;
	int flag = 0;

	while(1)
	{
		flag++;
		rat = recv(sock, &fi, sizeof(file_info), 0);
		if(rat != sizeof(file_info))
		{
			printf("传输完毕！\n");
			break;
		}
		
		ret = fi.size;
		name = fi.name;
		char* p = malloc(fi.size);
		printf("\n第 %d 个文件正在传输...\n", flag);
		printf("文件名：%s\n", name);
		printf("文件大小：%ld\n", ret);
		int fd = open(name, O_WRONLY | O_CREAT | O_TRUNC,0666);
		while(1)
		{
			if(ret < 1024 * 2)
			{
				recv(sock, p, ret, 0);
				write(fd, p, ret);
				printf("第 %d 个文件传输完毕！\n\n", flag);
				break;
			}
			k = recv(sock, p, 1024 * 2,0);
			write(fd, p, k);
			ret = ret - k;
			printf("剩余文件：%ld / %ld \r", ret , fi.size);
		}
		free(p);
		close(fd);
	}





	//第 5 步：关闭监听套接字
	close(sock);
	
	return 0;
}


